package remy;

import Engine.src.ca.uqac.dim.turtledb.*;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;

public class QueryOptimizer {

    private HashSet<String> sites; // PAS DE DOUBLONS AVEC UNE COLLECTION SET
    private Hashtable<String, String> fragments; // <Nom, Composition>
    private Hashtable<String, Set<String>> allocation_fragments; // <Site, Fragments>
    private Hashtable<String, Integer> couts_stockage; // <Site, Cout>
    private Hashtable<String, Hashtable<String, Integer>> couts_communication; // <Site 1 <Site 2, Cout>>

    public QueryOptimizer(){
        sites = new HashSet<String>();
        fragments = new Hashtable<String, String>();
        allocation_fragments = new Hashtable<String, Set<String>>();
        couts_stockage = new Hashtable<String, Integer>();
        couts_communication = new Hashtable<String, Hashtable<String,Integer>>();
    }

    public void setSites(HashSet<String> sites){
        this.sites = sites;
    }

    public void addSite(String site){
        sites.add(site);
    }

    public void removeSite(String site){
        sites.remove(site);
    }

    public void setFragments(Hashtable<String, String> fragments){
        this.fragments = fragments;
    }

    public void addFragment(String nom, String composition){
        fragments.put(nom, composition);
    }

    public void removeFragment(String nom){
        fragments.remove(nom);
    }

    public String getCompositionFragment(String nom){
        return fragments.get(nom);
    }

    public void setAllocationFragmentSite(String site, String fragment){
        if(allocation_fragments.containsKey(site)){
                allocation_fragments.get(site).add(fragment);
        }
        else{
                HashSet<String> h = new HashSet<String>();
                h.add(fragment);
                allocation_fragments.put(site, h);
        }
    }

    public void setCoutStockageSite(String site, int cout){
        couts_stockage.put(site, cout);
    }

    public int getCoutStockageSite(String site){
            return couts_stockage.get(site);
    }

    public void setCoutCommunication(String site1, String site2, int cout){
        if(couts_communication.containsKey(site1)){
                couts_communication.get(site1).put(site2, cout);
        }
        else{
                Hashtable<String, Integer> h = new Hashtable<String, Integer>();
                h.put(site2, cout);
                couts_communication.put(site1, h);
        }

        if(couts_communication.containsKey(site2)){
                couts_communication.get(site2).put(site1, cout);
        }
        else{
                Hashtable<String, Integer> h = new Hashtable<String, Integer>();
                h.put(site1, cout);
                couts_communication.put(site2, h);
        }
    }

    public int getCoutCommunication(String site1, String site2){
        return couts_communication.get(site1).get(site2);
    }

    public int getCost(QueryPlan p){
        int cout = 0;

        for(Map.Entry<String, Set<Relation>> entry : p.entrySet()){
                cout += getCoutStockageSite(entry.getKey());

                int nbtuples = 0;		
                for(Relation r : entry.getValue()){
                        nbtuples += r.getCardinality();
                }

                Hashtable<String, Integer> lCoutsComm = couts_communication.get(entry.getKey());

                for(String site : p.keySet()){

                        if(entry.getKey().compareTo(site) != 0){
                                if(lCoutsComm.containsKey(site)){
                                        cout += nbtuples * lCoutsComm.get(site);
                                }
                        }
                }
        }

        return cout;
    }

    public QueryPlan optimizeQuery(Relation q){

        return null;
    }

}